﻿using Qins.PluginInterface;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using System.Text;
using System.Threading.Tasks;

namespace Qins.PluginLoader
{
    public class _PluginAssemblyLoadContext : AssemblyLoadContext
    {
        /// <summary>
        /// 指定位置的插件库集合
        /// </summary>
        private AssemblyDependencyResolver _resolver;

        /// <summary>
        /// 构造函数
        /// isCollectible: true 重点，允许Unload
        /// </summary>
        /// <param name="pluginPath"></param>
        public _PluginAssemblyLoadContext(string pluginPath) : base(isCollectible: true)
        {
            _resolver = new AssemblyDependencyResolver(pluginPath);
        }

        protected override Assembly Load(AssemblyName assemblyName)
        {
            try
            {
                if (assemblyName.Name == typeof(IPlugin).Assembly.GetName().Name)
                {
                    return null;
                }

                string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);

                using (var fs = new FileStream(assemblyPath, FileMode.Open, FileAccess.Read))
                {
                    var _AssemblyLoadContext = new AssemblyLoadContext(Guid.NewGuid().ToString("N"), true);

                    var _Assembly = _AssemblyLoadContext.LoadFromStream(fs);
                    return _Assembly;
                }
            }
            catch (Exception ex) { 
                Console.WriteLine($"LoadFile:{ex.Message}"); 
            };
            return null;
        }

        private Assembly _AssemblyLoadContext_Resolving(AssemblyLoadContext arg1, AssemblyName arg2)
        {
            Console.WriteLine($"加载{arg2.Name}");
            var path = _resolver.ResolveAssemblyToPath(arg2);
            if (!string.IsNullOrEmpty(path))
            {
                using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
                {
                    return arg1.LoadFromStream(fs);
                }
            }
            return null;
        }

    }
}
